﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace GenerateAdminPage.Classes.Models
{
    #region USING
    using GenerateAdminPage.Classes.Base;
    using GenerateAdminPage.Classes.Helpers;
    using GenerateAdminPage.Classes.DBStructure;
    using System.Text;
    #endregion

    /// <summary>
    /// Generate Repository corresponding with each entity model
    /// </summary>
    public class Repository : AbstractBase, IRepository
    {
        /// <summary>
        /// Method is responsible for select generate type such as: view, frmclass or repository
        /// </summary>
        /// <returns>Correspding generate class</returns>
        public static AbstractBase SelectGenerateType(Table tbl, Table tblMany)
        {
            return new Repository();
        }

        public override string GenerateUsingRegion()
        {
            StringBuilder Result = new StringBuilder();

            Result.AppendLine(TAB + "#region using");
            Result.AppendLine(TAB + "using " + GlobalVariables.g_sNameSpace + ".Models;");
            Result.AppendLine(TAB + "using " + GlobalVariables.g_sNameSpace + ".Helpers;");
            Result.AppendLine(TAB + "#endregion");

            return Result.ToString();
        }

        public override string GenerateClass()
        {
            StringBuilder Result = new StringBuilder();

            Result.AppendLine(TAB + "public class " + TblOne.Name + "Repository");
            Result.AppendLine(TAB + "{");

            Result.AppendLine(GenerateSelectAll());
            Result.AppendLine(GenerateSelectByID());
            Result.AppendLine(GenerateInsert());
            Result.AppendLine(GenerateDelete());
            Result.AppendLine(GenerateSave());
            Result.AppendLine(GenerateRetrieveByID());
            
            for (int i = 0; i < TblOne.Attributes.Count; i++)
            {
                if (TblOne.Attributes[i].IsForeignKey)
                {
                    //generate select by foreign key
                    Result.AppendLine(GenerateSelectByForeignKey(TblOne.Attributes[i]));
                }
            }

            if (GlobalVariables.g_sTableNguoiDung.Contains(TblOne.Name))
            {
                Result.AppendLine(SelectByUserName());
                Result.AppendLine(SelectByUserNameAndPassword());
            }

            Result.AppendLine(TAB + "}");
            return Result.ToString();
        }

        public string GenerateSelectByForeignKey(Attribute FK)
        {
            StringBuilder Result = new StringBuilder();
            var idFK = FK.Name.ToLower();

            // Select item by foreign key and paging
            Result.AppendLine(TAB2 + "public static List<" + TblOne.Name + "> SelectBy" + FK.Name + "(" + Utils.GetDataType(FK.Type) + " " + idFK + ")");
            Result.AppendLine(TAB2 + "{");
            Result.AppendLine(TAB3 + "try");
            Result.AppendLine(TAB3 + "{");
            Result.AppendLine(TAB3 + "var lstItem = (from item in DataContext.Instance." + Utils.BuildModelName(DB, TblOne, TblOne.Name) + " where item." + FK.Name + " == " + idFK + " select item).ToList();");
            Result.AppendLine(TAB3 + "return lstItem;");
            Result.AppendLine(TAB3 + "}");
            Result.AppendLine(TAB3 + "catch(Exception ex)");
            Result.AppendLine(TAB3 + "{");
            Result.AppendLine(TAB4 + "if (ex.InnerException != null)");
            Result.AppendLine(TAB4 + "{");
            Result.AppendLine(TAB5 + "GlobalVariables.Logger.Error(ex.InnerException.Message);");
            Result.AppendLine(TAB4 + "}");
            Result.AppendLine(TAB4 + "else");
            Result.AppendLine(TAB4 + "{");
            Result.AppendLine(TAB5 + "GlobalVariables.Logger.Error(ex.Message);");
            Result.AppendLine(TAB4 + "}");
            Result.AppendLine(TAB3 + "}");
            Result.AppendLine(TAB3 + "return new List<" + TblOne.Name + ">();");
            Result.AppendLine(TAB2 + "}");

            return Result.ToString();
        }

        public string GenerateSelectByForeignKey(List<Attribute> FK)
        {
            StringBuilder Result = new StringBuilder();
            Result.AppendLine(TAB2 + "public static List<" + TblOne.Name + "> SelectBy" + FK[0].ReferTo + "(" + Utils.BuildFKParams(FK) + ")");
            Result.AppendLine(TAB2 + "{");
            Result.AppendLine(TAB3 + "try");
            Result.AppendLine(TAB3 + "{");
            Result.AppendLine(TAB4 + "var lstItem = (from item in DataContext.Instance." + Utils.BuildModelName(DB, TblOne, TblOne.Name) + " where " + Utils.BuildWhereClause(FK) + " select item).ToList();");
            Result.AppendLine(TAB4 + "return lstItem;");
            Result.AppendLine(TAB3 + "}");
            Result.AppendLine(TAB3 + "catch(Exception ex)");
            Result.AppendLine(TAB3 + "{");
            Result.AppendLine(TAB4 + "if (ex.InnerException != null)");
            Result.AppendLine(TAB4 + "{");
            Result.AppendLine(TAB5 + "GlobalVariables.Logger.Error(ex.InnerException.Message);");
            Result.AppendLine(TAB4 + "}");
            Result.AppendLine(TAB4 + "else");
            Result.AppendLine(TAB4 + "{");
            Result.AppendLine(TAB5 + "GlobalVariables.Logger.Error(ex.Message);");
            Result.AppendLine(TAB4 + "}");
            Result.AppendLine(TAB3 + "}");
            Result.AppendLine(TAB3 + "return new List<" + TblOne.Name + ">();");
            Result.AppendLine(TAB2 + "}");

            return Result.ToString();
        }

        public string GenerateRetrieveByID()
        {
            StringBuilder Result = new StringBuilder();
            var lst = Utils.PKHaveMoreThan1Attribute(TblOne);
            Result.AppendLine(TAB2 + "public static List<" + TblOne.Name + "> RetrieveByID(" + Utils.BuildPKParams(lst) + ")");
            Result.AppendLine(TAB2 + "{");
            Result.AppendLine(TAB3 + "try");
            Result.AppendLine(TAB3 + "{");
            Result.AppendLine(TAB4 + "return (from item in DataContext.Instance." + Utils.BuildModelName(DB, TblOne, TblOne.Name) + " where " + Utils.BuildPKWhereClause(lst) + " select item).ToList();");
            Result.AppendLine(TAB3 + "}");
            Result.AppendLine(TAB3 + "catch(Exception ex)");
            Result.AppendLine(TAB3 + "{");
            Result.AppendLine(TAB4 + "if (ex.InnerException != null)");
            Result.AppendLine(TAB4 + "{");
            Result.AppendLine(TAB5 + "GlobalVariables.Logger.Error(ex.InnerException.Message);");
            Result.AppendLine(TAB4 + "}");
            Result.AppendLine(TAB4 + "else");
            Result.AppendLine(TAB4 + "{");
            Result.AppendLine(TAB5 + "GlobalVariables.Logger.Error(ex.Message);");
            Result.AppendLine(TAB4 + "}");
            Result.AppendLine(TAB3 + "}");
            Result.AppendLine(TAB3 + "return new List<" + TblOne.Name + ">();");
            Result.AppendLine(TAB2 + "}");

            return Result.ToString();
        }

        public virtual string GenerateDelete()
        {
            StringBuilder Result = new StringBuilder();
            var lst = Utils.PKHaveMoreThan1Attribute(TblOne);
            Result.AppendLine(TAB2 + "public static bool Delete(" + Utils.BuildPKParams(lst) + ")");
            Result.AppendLine(TAB2 + "{");
            Result.AppendLine(TAB3 + "try");
            Result.AppendLine(TAB3 + "{");
            Result.AppendLine(TAB4 + "var delitem = DataContext.Instance." + Utils.BuildModelName(DB, TblOne, TblOne.Name) + ".FirstOrDefault(item =>" + Utils.BuildPKWhereClause(lst) + ");");
            Result.AppendLine(TAB4 + "DataContext.Instance." + Utils.BuildModelName(DB, TblOne, TblOne.Name) + ".DeleteObject(delitem);");
            Result.AppendLine(TAB4 + "DataContext.Instance.SaveChanges();");
            Result.AppendLine(TAB4 + "return true;");
            Result.AppendLine(TAB3 + "}");
            Result.AppendLine(TAB3 + "catch(Exception ex)");
            Result.AppendLine(TAB3 + "{");
            Result.AppendLine(TAB4 + "if (ex.InnerException != null)");
            Result.AppendLine(TAB4 + "{");
            Result.AppendLine(TAB5 + "GlobalVariables.Logger.Error(ex.InnerException.Message);");
            Result.AppendLine(TAB4 + "}");
            Result.AppendLine(TAB4 + "else");
            Result.AppendLine(TAB4 + "{");
            Result.AppendLine(TAB5 + "GlobalVariables.Logger.Error(ex.Message);");
            Result.AppendLine(TAB4 + "}");
            Result.AppendLine(TAB3 + "}");
            Result.AppendLine(TAB4 + "return false;");
            Result.AppendLine(TAB2 + "}");

            return Result.ToString();
        }

        public virtual string GenerateInsert()
        {
            StringBuilder Result = new StringBuilder();

            Result.AppendLine(TAB2 + "public static bool Insert(" + TblOne.Name + " obj)");
            Result.AppendLine(TAB2 + "{");
            Result.AppendLine(TAB3 + "try");
            Result.AppendLine(TAB3 + "{");
            Result.AppendLine(TAB4 + "DataContext.Instance." + Utils.BuildModelName(DB, TblOne, TblOne.Name) + ".AddObject(obj);");
            Result.AppendLine(TAB4 + "DataContext.Instance.SaveChanges();");
            Result.AppendLine(TAB4 + "return true;");
            Result.AppendLine(TAB3 + "}");
            Result.AppendLine(TAB3 + "catch(Exception ex)");
            Result.AppendLine(TAB3 + "{");
            Result.AppendLine(TAB4 + "if (ex.InnerException != null)");
            Result.AppendLine(TAB4 + "{");
            Result.AppendLine(TAB5 + "GlobalVariables.Logger.Error(ex.InnerException.Message);");
            Result.AppendLine(TAB4 + "}");
            Result.AppendLine(TAB4 + "else");
            Result.AppendLine(TAB4 + "{");
            Result.AppendLine(TAB5 + "GlobalVariables.Logger.Error(ex.Message);");
            Result.AppendLine(TAB4 + "}");
            Result.AppendLine(TAB3 + "}");
            Result.AppendLine(TAB4 + "return false;");
            Result.AppendLine(TAB2 + "}");

            return Result.ToString();
        }

        public virtual string GenerateSelectAll()
        {
            StringBuilder Result = new StringBuilder();

            Result.AppendLine(TAB2 + "public static List<" + TblOne.Name + "> SelectAll()");
            Result.AppendLine(TAB2 + "{");
            Result.AppendLine(TAB3 + "try");
            Result.AppendLine(TAB3 + "{");
            Result.AppendLine(TAB4 + "return DataContext.Instance." + Utils.BuildModelName(DB, TblOne, TblOne.Name) + ".ToList();");
            Result.AppendLine(TAB3 + "}");
            Result.AppendLine(TAB3 + "catch(Exception ex)");
            Result.AppendLine(TAB3 + "{");
            Result.AppendLine(TAB4 + "if (ex.InnerException != null)");
            Result.AppendLine(TAB4 + "{");
            Result.AppendLine(TAB5 + "GlobalVariables.Logger.Error(ex.InnerException.Message);");
            Result.AppendLine(TAB4 + "}");
            Result.AppendLine(TAB4 + "else");
            Result.AppendLine(TAB4 + "{");
            Result.AppendLine(TAB5 + "GlobalVariables.Logger.Error(ex.Message);");
            Result.AppendLine(TAB4 + "}");
            Result.AppendLine(TAB3 + "}");
            Result.AppendLine(TAB3 + "return new List<" + TblOne.Name + ">();");
            Result.AppendLine(TAB2 + "}");

            return Result.ToString();
        }

        public virtual string GenerateSelectByID()
        {
            StringBuilder Result = new StringBuilder();
            var lst = Utils.PKHaveMoreThan1Attribute(TblOne);
            Result.AppendLine(TAB2 + "public static " + TblOne.Name + " SelectByID(" + Utils.BuildPKParams(lst) + ")");
            Result.AppendLine(TAB2 + "{");
            Result.AppendLine(TAB3 + "try");
            Result.AppendLine(TAB3 + "{");
            Result.AppendLine(TAB4 + "return DataContext.Instance." + Utils.BuildModelName(DB, TblOne, TblOne.Name) + ".FirstOrDefault(item =>" + Utils.BuildPKWhereClause(lst) + ");");
            Result.AppendLine(TAB3 + "}");
            Result.AppendLine(TAB3 + "catch(Exception ex)");
            Result.AppendLine(TAB3 + "{");
            Result.AppendLine(TAB4 + "if (ex.InnerException != null)");
            Result.AppendLine(TAB4 + "{");
            Result.AppendLine(TAB5 + "GlobalVariables.Logger.Error(ex.InnerException.Message);");
            Result.AppendLine(TAB4 + "}");
            Result.AppendLine(TAB4 + "else");
            Result.AppendLine(TAB4 + "{");
            Result.AppendLine(TAB5 + "GlobalVariables.Logger.Error(ex.Message);");
            Result.AppendLine(TAB4 + "}");
            Result.AppendLine(TAB3 + "}");
            Result.AppendLine(TAB3 + "return null;");
            Result.AppendLine(TAB2 + "}");

            return Result.ToString();
        }

        public string GenerateSave()
        {
            StringBuilder Result = new StringBuilder();

            Result.AppendLine(TAB2 + "public static bool Save()");
            Result.AppendLine(TAB2 + "{");
            Result.AppendLine(TAB3 + "try");
            Result.AppendLine(TAB3 + "{");
            Result.AppendLine(TAB4 + "DataContext.Instance.SaveChanges();");
            Result.AppendLine(TAB4 + "return true;");
            Result.AppendLine(TAB3 + "}");
            Result.AppendLine(TAB3 + "catch(Exception ex)");
            Result.AppendLine(TAB3 + "{");
            Result.AppendLine(TAB4 + "if (ex.InnerException != null)");
            Result.AppendLine(TAB4 + "{");
            Result.AppendLine(TAB5 + "GlobalVariables.Logger.Error(ex.InnerException.Message);");
            Result.AppendLine(TAB4 + "}");
            Result.AppendLine(TAB4 + "else");
            Result.AppendLine(TAB4 + "{");
            Result.AppendLine(TAB5 + "GlobalVariables.Logger.Error(ex.Message);");
            Result.AppendLine(TAB4 + "}");
            Result.AppendLine(TAB3 + "}");
            Result.AppendLine(TAB4 + "return false;");
            Result.AppendLine(TAB2 + "}");

            return Result.ToString();
        }

        public string SelectByUserName()
        {
            StringBuilder Result = new StringBuilder();

            Result.AppendLine(TAB2 + "public static " + TblOne.Name + " SelectByUserName(string username)");
            Result.AppendLine(TAB2 + "{");
            Result.AppendLine(TAB3 + "try");
            Result.AppendLine(TAB3 + "{");
            Result.AppendLine(TAB4 + "return DataContext.Instance." + TblOne.Name + ".FirstOrDefault(item => item.TenDangNhap == username);");
            Result.AppendLine(TAB3 + "}");
            Result.AppendLine(TAB3 + "catch(Exception ex)");
            Result.AppendLine(TAB3 + "{");
            Result.AppendLine(TAB4 + "if (ex.InnerException != null)");
            Result.AppendLine(TAB4 + "{");
            Result.AppendLine(TAB5 + "GlobalVariables.Logger.Error(ex.InnerException.Message);");
            Result.AppendLine(TAB4 + "}");
            Result.AppendLine(TAB4 + "else");
            Result.AppendLine(TAB4 + "{");
            Result.AppendLine(TAB5 + "GlobalVariables.Logger.Error(ex.Message);");
            Result.AppendLine(TAB4 + "}");
            Result.AppendLine(TAB3 + "}");
            Result.AppendLine(TAB4 + "return null;");
            Result.AppendLine(TAB2 + "}");

            return Result.ToString();
        }

        public string SelectByUserNameAndPassword()
        {
            StringBuilder Result = new StringBuilder();

            Result.AppendLine(TAB2 + "public static " + TblOne.Name + " SelectByUserNameAndPassword(string username, string password)");
            Result.AppendLine(TAB2 + "{");
            Result.AppendLine(TAB3 + "try");
            Result.AppendLine(TAB3 + "{");
            Result.AppendLine(TAB4 + "return DataContext.Instance." + TblOne.Name + ".FirstOrDefault(item => item.TenDangNhap == username && item.MatKhau == password);");
            Result.AppendLine(TAB3 + "}");
            Result.AppendLine(TAB3 + "catch(Exception ex)");
            Result.AppendLine(TAB3 + "{");
            Result.AppendLine(TAB4 + "if (ex.InnerException != null)");
            Result.AppendLine(TAB4 + "{");
            Result.AppendLine(TAB5 + "GlobalVariables.Logger.Error(ex.InnerException.Message);");
            Result.AppendLine(TAB4 + "}");
            Result.AppendLine(TAB4 + "else");
            Result.AppendLine(TAB4 + "{");
            Result.AppendLine(TAB5 + "GlobalVariables.Logger.Error(ex.Message);");
            Result.AppendLine(TAB4 + "}");
            Result.AppendLine(TAB3 + "}");
            Result.AppendLine(TAB4 + "return null;");
            Result.AppendLine(TAB2 + "}");

            return Result.ToString();
        }
    }
}
